package org.brakepedal.server.support.http;

import jakarta.servlet.http.HttpServletResponse;
import lombok.experimental.SuperBuilder;
import org.jetbrains.annotations.NotNull;

/**
 * Date: 2023/2/9 17:04

 
 */
@SuperBuilder
public class AbsResponseBody {
    protected ResponseBodyCode code;

    protected ResponseBodyStatus status;

    protected ResponseBodyMsg msg;

    protected Object data;

    private final static int fieldCount =  AbsResponseBody.class.getDeclaredFields().length - 1;

    protected AbsResponseBody() {
        reset();
    }

    public AbsResponseBody(ResponseBodyCode code, ResponseBodyStatus status, ResponseBodyMsg msg, Object data) {
        this.code = code;
        this.status = status;
        this.msg = msg;
        this.data = data;
    }

    public AbsResponseBody(ResponseBodyCode code, ResponseBodyStatus status, ResponseBodyMsg msg) {
        this.code = code;
        this.status = status;
        this.msg = msg;
    }

    public AbsResponseBody setWarnBadResponse(HttpServletResponse response, ResponseBodyMsg msg) {
        setMsg(msg);
        setCodeAndUpdateHttpResponse(ResponseBodyCode.BAD_REQUEST,response);
        setStatus(ResponseBodyStatus.WARN);
        return this;
    }

    public AbsResponseBody setWarnBadResponse(ResponseBodyMsg msg) {
        setMsg(msg);
        setCode(ResponseBodyCode.BAD_REQUEST);
        setStatus(ResponseBodyStatus.WARN);
        return this;
    }

    public AbsResponseBody reset() {
        setMsg(ResponseBodyMsg.OK);
        setStatus(ResponseBodyStatus.SUCCESS);
        setCode(ResponseBodyCode.SUCCESS);
        setData(null);
        return this;
    }

    public static AbsResponseBody mixIntoFirst(AbsResponseBody @NotNull ...sources) {
        boolean[] isFirst = new boolean[fieldCount];
        int breakCount = 0;
        AbsResponseBody target = sources[0];
        for (int i = sources.length-1; i > 0 ; i--) {
            final AbsResponseBody source= sources[i];
            if(!isFirst[0] && ! ResponseBodyCode.SUCCESS.hasSameValue(source.getCode())) {
                isFirst[0] = true;
                breakCount++;
                target.setCode(source.getCode());
            }
            if(!isFirst[1] && !ResponseBodyStatus.SUCCESS.hasSameValue(source.getStatus())) {
                isFirst[1] = true;
                breakCount++;
                target.setStatus(source.getStatus());
            }
            if(!isFirst[2] && !ResponseBodyMsg.OK.hasSameValue(source.getMsg())) {
                isFirst[2] = true;
                breakCount++;
                target.setMsg(source.getMsg());
            }
            Object sourceData = source.getData();
            if(!isFirst[3] && target.getData() == null && sourceData != null) {
                isFirst[3] = true;
                breakCount++;
                target.setData(sourceData);
            }
            if(breakCount>=isFirst.length) {
                break;
            }
        }
        return target;
    }

    public ResponseBodyCode getCode() {
        return code;
    }

    public AbsResponseBody setCodeAndUpdateHttpResponse(ResponseBodyCode code, @NotNull HttpServletResponse response) {
        setCode(code);
        response.setStatus(code.getValue());
        return this;
    }

    public AbsResponseBody setCode(ResponseBodyCode code) {
        this.code = code;
        return this;
    }

    public ResponseBodyStatus getStatus() {
        return status;
    }

    public AbsResponseBody setStatus(ResponseBodyStatus status) {
        this.status = status;
        return this;
    }

    public ResponseBodyMsg getMsg() {
        return msg;
    }

    public AbsResponseBody setMsg(ResponseBodyMsg msg) {
        this.msg = msg;
        return this;
    }

    public Object getData() {
        return data;
    }

    public AbsResponseBody setData(Object data) {
        this.data = data;
        return this;
    }

    @Override
    public String toString() {
        return "{" +
                "code=" + code +
                ", status='" + status + '\'' +
                ", msg='" + msg + '\'' +
                ", data=" + data +
                '}';
    }
}
